Imports DataAccessLayer

Public Class BLSecurityMgmt
    'Inherits Cryptography.Cryptography

    ''' <summary>
    ''' Encryption Key used in this application
    ''' </summary>
    ''' <remarks>Should NOT be modified</remarks>
    Private sEncryptionKey As String
    Dim dtSettingsMain As DataTable

    Public Sub New()
        Dim _DLSettings As DLSettings
        Try
            _DLSettings = New DLSettings
            dtSettingsMain = _DLSettings.FetchAllSettings 'CType(_DLSettings.FetchSettings("", "", "", DLSettings.eSettingsReturnType.DataTable), DataTable)
            sEncryptionKey = CStr(DLSettings.FetchOneSetting(dtSettingsMain, "Cryptography", "EncryptionKey"))
        Finally
            _DLSettings = Nothing
        End Try
    End Sub

    ''' <summary>
    ''' NO COMMENTS
    ''' </summary>
    ''' <param name="sIn"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Encryptor(ByVal sIn As String) As String
        Dim sEncryptedText As String
        Dim _DLSettings As DLSettings
        Dim iEncryptLevel As Integer

        Try
            _DLSettings = New DLSettings
            sEncryptedText = sIn
            iEncryptLevel = CInt(DLSettings.FetchOneSetting(dtSettingsMain, "PswdMgmt", "EncryptionLevel", ""))

            For iEachEncryptLevel As Integer = 1 To CInt(IIf(iEncryptLevel < 1, 1, iEncryptLevel))
                sEncryptedText = EncryptTripleDES(sEncryptedText)
            Next

            Return sEncryptedText

        Finally
            sIn = Nothing
            sEncryptedText = Nothing
            _DLSettings = Nothing
        End Try
    End Function

    ''' <summary>
    ''' NO COMMENTS
    ''' </summary>
    ''' <param name="sOut"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Decryptor(ByVal sOut As String) As String
        Dim sDecryptedText As String
        Dim _DLSettings As DLSettings
        Dim iDecryptLevel As Integer

        Try
            sDecryptedText = ""
            _DLSettings = New DLSettings
            iDecryptLevel = CInt(DLSettings.FetchOneSetting(dtSettingsMain, "PswdMgmt", "EncryptionLevel", ""))

            If iDecryptLevel < 1 Then iDecryptLevel = 1
            For iEachDecryptLevel As Integer = 1 To iDecryptLevel
                sDecryptedText = DecryptTripleDES(sDecryptedText)
            Next

            Return sDecryptedText

        Finally
            sDecryptedText = Nothing
            _DLSettings = Nothing
        End Try
    End Function

    ''' <summary>
    ''' NO COMMENTS
    ''' </summary>
    ''' <param name="sIn"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function EncryptTripleDES(ByVal sIn As String) As String
        Dim oCrypto As Cryptography.Cryptography
        Try
            oCrypto = New Cryptography.Cryptography(sEncryptionKey)
            Return oCrypto.EncryptTripleDES(sIn)
        Finally
            oCrypto = Nothing
        End Try
    End Function

    ''' <summary>
    ''' NO COMMENTS
    ''' </summary>
    ''' <param name="sOut"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function DecryptTripleDES(ByVal sOut As String) As String
        Dim oCrypto As Cryptography.Cryptography
        Try
            oCrypto = New Cryptography.Cryptography(sEncryptionKey)
            Return oCrypto.EncryptTripleDES(sOut)
        Finally
            oCrypto = Nothing
        End Try
    End Function

    ''' <summary>
    ''' Fetches auto-generated password
    ''' </summary>
    ''' <returns>Auto-generated password</returns>
    ''' <remarks></remarks>
    Friend Function FetchNewPassword() As String
        Dim _SLValidations As New SecurityManagementLayer.SLValidations
        Dim sNewPswd As String
        Try
            _SLValidations = New SecurityManagementLayer.SLValidations
            sNewPswd = GenerateNewPassword()
            While Not _SLValidations.ValidatePassword(sNewPswd)
                sNewPswd = GenerateNewPassword()
            End While
            Return sNewPswd
        Finally
            _SLValidations = Nothing
            sNewPswd = Nothing
        End Try
    End Function

    ''' <summary>
    ''' Generates new password
    ''' </summary>
    ''' <returns>Auto-generated password</returns>
    ''' <remarks></remarks>
    Private Function GenerateNewPassword() As String
        Dim sNewPswd As String = ""
        Dim iLength, iElem As Integer
        Dim arrJaggedKeys()() As String 'Jagged Array
        Dim arrConsonants(), arrVowels(), arrSpChar(), arrNumerals() As String
        Dim iToggle As Integer
        Dim _DLSettings As DLSettings

        Try
            _DLSettings = New DLSettings
            iLength = CInt(DLSettings.FetchOneSetting(dtSettingsMain, "PswdMgmt", "PasswordLength"))
            arrJaggedKeys = New String(4)() {}
            arrSpChar = "!,@,#,$,%,&,*,+,-,_".Replace(" ", "").Split(",".ToCharArray, StringSplitOptions.RemoveEmptyEntries)
            arrVowels = "A,AI,AU,E,EA,EE,I,IA,IO,O,OA,OI,OO,OU,U".Replace(" ", "").Split(",".ToCharArray, StringSplitOptions.RemoveEmptyEntries)
            arrConsonants = "B,C,CH,CL,D,F,FF,G,GH,GL,J,K,L,LL,M,MN,N,P,PH,PS,R,RH,S,SC,SH,SK,ST,T,TH,V,W,X,Y,Z".Replace(" ", "").Split(",".ToCharArray, StringSplitOptions.RemoveEmptyEntries)
            arrNumerals = "0,1,2,3,4,5,6,7,8,9".Replace(" ", "").Split(",".ToCharArray, StringSplitOptions.RemoveEmptyEntries)

            arrJaggedKeys(0) = arrSpChar
            arrJaggedKeys(1) = arrVowels
            arrJaggedKeys(2) = arrConsonants
            arrJaggedKeys(3) = arrNumerals

            For iLoop As Integer = 1 To iLength
                ' '' ''Hard-coded approach
                '' ''iToggle = CInt(GenerateRandomNumber()) Mod 4
                '' ''Select Case iToggle
                '' ''    Case 0 'sp. characters
                '' ''        iElem = CInt(GenerateRandomNumber()) Mod arrSpChar.Length
                '' ''        sNewPswd &= IIf(CInt(GenerateRandomNumber()) Mod 2 = 0, LCase(arrSpChar(iElem)), UCase(arrSpChar(iElem))).ToString
                '' ''    Case 1 'vowels
                '' ''        iElem = CInt(GenerateRandomNumber()) Mod arrVowels.Length
                '' ''        sNewPswd &= IIf(CInt(GenerateRandomNumber()) Mod 2 = 0, LCase(arrVowels(iElem)), UCase(arrVowels(iElem))).ToString
                '' ''    Case 2 'consonants
                '' ''        iElem = CInt(GenerateRandomNumber()) Mod arrConsonants.Length
                '' ''        sNewPswd &= IIf(CInt(GenerateRandomNumber()) Mod 2 = 0, LCase(arrConsonants(iElem)), UCase(arrConsonants(iElem))).ToString
                '' ''    Case 3 'numerals
                '' ''        iElem = CInt(GenerateRandomNumber()) Mod arrNumerals.Length
                '' ''        sNewPswd &= arrNumerals(iElem)
                '' ''End Select

                'Dynamic approach
                iToggle = CInt(GenerateRandomNumber()) Mod arrJaggedKeys.Length
                iElem = CInt(GenerateRandomNumber()) Mod arrJaggedKeys(iToggle).Length
                sNewPswd &= IIf(CInt(GenerateRandomNumber()) Mod 2 = 0, LCase(arrJaggedKeys(iToggle)(iElem)), UCase(arrJaggedKeys(iToggle)(iElem))).ToString
            Next
            Return sNewPswd

        Finally
            _DLSettings = Nothing
            sNewPswd = Nothing
            iLength = Nothing
            iToggle = Nothing
            Erase arrJaggedKeys
            Erase arrConsonants
            Erase arrVowels
            Erase arrSpChar
        End Try
    End Function

    ''' <summary>
    ''' Generates Random Number in the specified range (default: 0-5000)
    ''' </summary>
    ''' <param name="iRangeMin">Range minimum (default: 0)</param>
    ''' <param name="iRangeMax">Range maximum (default: 5000)</param>
    ''' <returns>A random number in the specified range</returns>
    ''' <remarks></remarks>
    Private Function GenerateRandomNumber(Optional ByVal iRangeMin As Integer = 0, Optional ByVal iRangeMax As Integer = 5000) As Double
        Dim _Random As System.Random
        Try
            _Random = New System.Random(CInt(System.DateTime.Now.Ticks Mod System.Int32.MaxValue))
            'Return CInt(VBMath.Rnd() * 1000)
            System.Threading.Thread.Sleep(10)
            Return _Random.Next(iRangeMin, iRangeMax)
        Finally
            _Random = Nothing
        End Try
    End Function

End Class
